using System;
using System.IO;
using System.Reflection;
using System.Xml.XPath;

namespace Gazebo.Core
{
    public static class Extensions
    {
        public static void WriteFully(this Stream stream, byte[] buffer) {
            stream.Write(buffer, 0, buffer.Length);
        }
        
        public static T GetCustomAttribute<T>(this MemberInfo member, bool inherit) where T : Attribute {
            object[] attrs = member.GetCustomAttributes(typeof(T), inherit);
            
            if (attrs.Length == 0) {
                return null;
            }
            
            return (T) attrs[0];
        }
        
        public static bool IsDataMember(this MemberInfo member)
        {
            return member is FieldInfo || member is PropertyInfo;
        }
        
        public static Type GetDataMemberType(this MemberInfo member)
        {
            PropertyInfo property = member as PropertyInfo;
            if (property != null) {
                return property.PropertyType;
            }
            
            FieldInfo field = member as FieldInfo;
            if (field != null) {
                return field.FieldType;
            }
            
            return null;
        }
        
        public static void SetDataMember(this MemberInfo member, object obj, object data)
        {
            PropertyInfo property = member as PropertyInfo;
            if (property != null) {
                property.SetValue(obj, data, null);
                return;
            }
            
            FieldInfo field = member as FieldInfo;
            if (field != null) {
                field.SetValue(obj, data);
                return;
            }
            
            throw new ArgumentException("member: Not a PropertyInfo or a FieldInfo.");
        }
        
        public static object GetDataMember(this MemberInfo member, object obj)
        {
            PropertyInfo property = member as PropertyInfo;
            if (property != null) {
                return property.GetValue(obj, null);
            }
            
            FieldInfo field = member as FieldInfo;
            if (field != null) {
                return field.GetValue(obj);
            }
            
            throw new ArgumentException("member: Not a PropertyInfo or a FieldInfo.");
        }
    }
}
